﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Windows.Forms;
using System.IO;

namespace ChatTool
{
    /// <summary>
    /// 单个文件的传送接受
    /// </summary>
    public class FileTransfer
    {
        private FormChatToOne formChatToOne;
        private string fileName;
        private UserClient userClient;
        private FileStream fs;

        ToolStrip ts = new ToolStrip();
        ToolStripProgressBar tspb = new ToolStripProgressBar();
        ToolStripButton tsb = new ToolStripButton();

        public FileTransfer(FormChatToOne formChatToOne, string fileName)
        {
            this.formChatToOne = formChatToOne;
            this.fileName = fileName;

            tsb.Text = "发送";
            tsb.Click += new EventHandler(tsb_Click);
            ts.GripStyle = ToolStripGripStyle.Hidden;
            ts.BackColor = System.Drawing.Color.Transparent;
            ts.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { tspb, tsb });          
        }
        /// <summary>
        /// 发送文件
        /// </summary>
        public void Send()
        {
            try
            {
                fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                if (fs.Length > 2147483647)
                {
                    MessageBox.Show("最大支持2GB的文件发送,当前文件大于2GB.");
                    return;
                }
                this.formChatToOne.AddOrDeleteToolStripToPanel("Add", ts);
                this.tspb.Value = 0;
                this.tspb.Maximum = (int)fs.Length;
                this.tspb.AutoSize = false;
                this.tspb.Size = new System.Drawing.Size(100, 15);
                string fileSize = Tool.GetFileSizeFromByteCount(fs.Length);
                tspb.ToolTipText = Path.GetFileName(fileName) + " [文件大小: " + fileSize + "]";
            }
            catch (Exception)
            {
                MessageBox.Show("要发送名为[" + Path.GetFileName(fileName) + "]的文件不能够打开,无法发送此文件!");
                fs.Close();
                return;
            }
        }
        //响应单击发送文件按钮
        private void tsb_Click(object sender, EventArgs e)
        {
            ToolStripButton tsb = sender as ToolStripButton;
            string text = tsb.Text;
            if (text == "发送")
            {
                if (ConnectToServer() == false)
                {
                    this.formChatToOne.AddOrDeleteToolStripToPanel("Delete", ts);
                }
                else
                {
                    tsb.Text = "中止";
                    Thread receiveThread = new Thread(ReceiveServerData);
                    receiveThread.IsBackground = true;
                    receiveThread.Start();

                    NetManager.SendStringMsgToServer(userClient, "TransferFile");
                    NetManager.SendStringMsgToServer(userClient, Path.GetFileName(fileName));//传送文件名
                    //这里还要发送文件的大小给对方
                    NetManager.SendStringMsgToServer(userClient, fs.Length.ToString());
                }
            }
            else
            {
                //NetManager.SendStringMsgToServer(userClient, "stop");
                userClient.Close();
                this.formChatToOne.AddOrDeleteToolStripToPanel("Delete", ts);
            }
        }
        //连接对方
        private bool ConnectToServer()
        {
            TcpClient client = new TcpClient(AddressFamily.InterNetwork);
            try
            {
                IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(this.formChatToOne.UserClient.User.Ip), this.formChatToOne.UserClient.User.ListenerPort);
                client.Connect(ipe);//连接服务器
            }
            catch (Exception)
            {
                client.Close();
                MessageBox.Show("对方服务器未开启,无法发送文件!");
                return false;
            }
            userClient = new UserClient(client);
            return true;
        }
        //接受对方的信息
        private void ReceiveServerData()
        {
            while (true)
            {
                try
                {
                    string command = userClient.Br.ReadString().ToLower();
                    switch (command.ToLower())
                    {
                        case "refuse":
                            this.formChatToOne.AddOrDeleteToolStripToPanel("Delete", ts);
                            userClient.Close();
                            return;
                        case "agree"://对方已经做好了接受文件的准备
                            StartFileSendThread();
                            break;
                        default:
                            break;
                    }
                }
                catch (Exception)
                {
                    this.formChatToOne.AddOrDeleteToolStripToPanel("Delete", ts);
                    userClient.Close();
                    break;
                }
            }
        }
        //启动文件发送线程
        private void StartFileSendThread()
        {
            Thread fileSendThread = new Thread(FileSend);
            fileSendThread.IsBackground = true;
            fileSendThread.Start();
        }
        //文件发送方法体
        private void FileSend()
        {
            try
            {
                int bufferLen = 1024 * 1024;//定义1Mb的发送缓冲区
                byte[] buffer = new byte[bufferLen];
                int readLen = 0;
                System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
                watch.Start();
                while ((readLen = fs.Read(buffer, 0, bufferLen)) != 0)
                {
                    userClient.Bw.Write(readLen);
                    userClient.Bw.Write(buffer, 0, readLen);
                    userClient.Bw.Flush();
                    //改变发送进度条的进度值 此处操作别的线程创建的控件 用委托执行 
                    this.HandleSysncContrl(tspb, "UpdateProgressRate", readLen.ToString());
                }
                watch.Stop();
                long useTimeMS = watch.ElapsedMilliseconds;
                long useTimeS = useTimeMS / 1000;
                long useTimeMin = useTimeS / 60;
                string useTimeStr = "";
                if (useTimeMin >= 1)
                    useTimeStr = useTimeMin + "分";
                else if (useTimeS >= 1)
                    useTimeStr = useTimeS + "秒";
                else
                    useTimeStr = useTimeMS + "毫秒";
                double speedKB = (1.0 * this.fs.Length / 1024) / (useTimeMS / 1000);//   KB/S表示
                double speedMB = 1.0 * speedKB / 1024;//  MB/S表示
                string speedStr = "";
                if (speedMB >= 1.0)
                    speedStr = string.Format("{0:0.##}MB/S", speedMB);
                else
                    speedStr = (int)speedKB + "";
                string waringInfo = "文件[" + this.fileName + "]传送完毕,用时:" + useTimeStr + ",平均传送速度:" + speedStr;
                this.formChatToOne.AddWaringInfoToRtContent(waringInfo);
                //这里可以提示文件成功发送完毕
            }
            catch (Exception ee)
            {
                MessageBox.Show("文件传送异常: " + ee.Message);
            }
            finally
            {
                fs.Close();
                userClient.Close();
                this.formChatToOne.AddOrDeleteToolStripToPanel("Delete", ts); 
            }
        }
        private delegate void HandleSysncControlDelegate(Object control, string cmd, string data);
        /// <summary>
        /// 异步操作控件
        /// </summary>
        private void HandleSysncContrl(Object control, string cmd, string data)
        {
            HandleSysncControlDelegate d = ExecHandleSysncContrl;
            this.formChatToOne.Invoke(d, control, cmd, data);
        }
        private void ExecHandleSysncContrl(Object control, string cmd, string data)
        {
            if (control is ToolStripProgressBar)
            {
                ToolStripProgressBar toolBar = control as ToolStripProgressBar;
                if (cmd == "UpdateProgressRate")
                    toolBar.Value += Int32.Parse(data);
            }
        }
    }
}
